<?php
namespace Swiftx\Component\Application;
use Swiftx\Component\Ioc\Container;
use Swiftx\Interfaces\Application\Config;
use Swiftx\Interfaces\Application\Server as ServerInterface;
use Swiftx\Interfaces\Application\Kernel as KernelInterface;
use Swiftx\Interfaces\Bundle\Kernel as BundleInterface;
use Swiftx\Interfaces\Ioc\Container as ContainerInterface;

/**
 * 应用程序内核接口类
 * @package Swiftx\Application
 */
class Kernel extends Container implements KernelInterface {

    /**
     * 服务器对象
     * @var ServerInterface
     */
    protected $server = null;

    /**
     * 配置对象
     * @var Config
     */
    protected $config = null;

    /**
     * 系统模块
     * @var BundleInterface[]
     */
    protected $bundles = [];

    /**
     * 创建一个 HTTP 内核实例
     * @param ServerInterface $server
     */
    public function __construct(ServerInterface $server = null) {
        $this->server = $server;
        $this->config = $server->parseConfig();
        $this->bindEntity(ServerInterface::class, $this->server, true);
        $this->bindEntity(KernelInterface::class, $this, true);
        $this->bindEntity(ContainerInterface::class, $this, true);
        $this->init();
    }

    /**
     * 获取配置对象
     * @return Config
     */
    public function getConfig():Config{
        return $this->config;
    }

    /**
     * 注册Bundle组件
     * @param BundleInterface $object
     */
    public function registerBundle(BundleInterface $object){
        if(isset($this->bundles[$object->getName()])) return;
        $this->bundles[$object->getName()] = $object;
        $this->bindEntity(get_class($object), $object, true);
    }

    /**
     * 项目初始化
     */
    public function init(){ }

    /**
     * 启动内核引导
     */
    public function boot(){
        // 启动模块引导
        foreach($this->bundles as $bundle)
            $this->bootBundle($bundle);
    }

    /**
     * 启动内核引导
     */
    public function build(){
        // 启动模块引导
        foreach($this->bundles as $bundle)
            $this->bootBundle($bundle);
    }

    /**
     * 启动Bundle模块
     * @param BundleInterface $object
     * @throws \ErrorException
     */
    protected function bootBundle(BundleInterface $object) {
        $depends = $object->getDependents();
        foreach($depends as $value){
            if(!isset($this->bundles[$value]))
                throw new \ErrorException('依赖Bundle未注册：'.$value);
            $this->bootBundle($this->bundles[$value]);
        }
        $object->boot($this);
    }

}